package com.jnc.pay.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.jnc.pay.biz.common.vo.PayChangeReq;
import com.jnc.pay.biz.common.vo.PayReq;
import com.jnc.pay.biz.common.vo.RefundReq;
import com.jnc.pay.constant.AliPayConstant;
import com.jnc.pay.constant.BizConstant;
import com.jnc.pay.constant.WechatPayConstant;
import com.jnc.pay.core.enumm.RateTypeEnum;
import com.jnc.pay.core.model.BaseReq;
import com.jnc.pay.core.model.BaseResp;
import com.jnc.pay.core.model.RespCode;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.HibernateValidator;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

/**
 * @Auther: jjn
 * @Date: 2020/6/24 11:19
 * @Desc: hibernator-validator校验工具类
 */
@Slf4j
public class ValidatorUtil {

    private static Validator validator;

    static {
        //快速失败返回模式
        validator = Validation.byProvider(HibernateValidator.class)
                .configure()
                .failFast(true)
                .buildValidatorFactory()
                .getValidator();
    }

    /**
     * 校验参数
     * @param req
     * @return
     */
    public static BaseResp valid(BaseReq req){
        Set<ConstraintViolation<BaseReq>> validates = validator.validate(req);
        if(CollectionUtil.isNotEmpty(validates)){
            //迭代取第一个
            ConstraintViolation<BaseReq> next = validates.iterator().next();
            log.warn("request parameter verification error: [{}]{}", next.getPropertyPath(), next.getMessage());
            String msg = "[" + next.getPropertyPath() + "]" + next.getMessage();
            return BaseResp.resp(RespCode.ILLEGAL_ARGUMENT.getCode(), msg, null);
        }
        return BaseResp.success();
    }

    /**
     * 校验特定支付交易参数
     * @param req
     * @return
     */
    public static BaseResp payValid(PayReq req){
        BaseResp resp = new BaseResp();
        //判断币种类型
        if(StrUtil.isBlank(req.getCurrencyCode())){
            req.setCurrencyCode(RateTypeEnum.CNY.getType());
        }
        boolean flag = RateTypeEnum.exist(req.getCurrencyCode());
        if(!flag){
            String msg = "Unsupported currency code [" + req.getCurrencyCode() + "]";
            log.warn("[PayHandler.pay] parameter verification error: {}", msg);
            return BaseResp.resp(RespCode.ILLEGAL_ARGUMENT.getCode(), msg, null);
        }
        //金额对应的小数位数(默认2位)
        if(req.getScale() == null){
            req.setScale(2);
        }
        switch (req.getChannelId()){
            case BizConstant.CHANNEL_ID_WX:
                resp = payWechatValid(req);
                return resp;
            case BizConstant.CHANNEL_ID_ALI:
                resp = payAliValid(req);
                return resp;
            default:
                log.warn("Invalid channelId: {}", req.getChannelId());
                resp.setCode(RespCode.ERROR.getCode()).setMsg("Invalid channelId: " + req.getChannelId());
                return resp;
        }
    }

    /**
     * 校验特定退款交易参数
     * @param req
     * @return
     */
    public static BaseResp refundValid(RefundReq req){
        BaseResp resp = new BaseResp();
        //判断币种类型
        if(StrUtil.isBlank(req.getCurrencyCode())){
            req.setCurrencyCode(RateTypeEnum.CNY.getType());
        }
        boolean flag = RateTypeEnum.exist(req.getCurrencyCode());
        if(!flag){
            String msg = "Unsupported currency code [" + req.getCurrencyCode() + "]";
            log.warn("[PayHandler.refund] parameter verification error: {}", msg);
            return BaseResp.resp(RespCode.ILLEGAL_ARGUMENT.getCode(), msg, null);
        }
        //金额对应的小数位数(默认2位)
        if(req.getScale() == null){
            req.setScale(2);
        }
        switch (req.getChannelId()){
            case BizConstant.CHANNEL_ID_WX:
                return resp;
            case BizConstant.CHANNEL_ID_ALI:
                return resp;
            default:
                log.warn("Invalid channelId: {}", req.getChannelId());
                resp.setCode(RespCode.ERROR.getCode()).setMsg("Invalid channelId: " + req.getChannelId());
                return resp;
        }
    }

    /**
     * 微信企业付款到零钱参数校验
     * @param req
     * @return
     */
    public static BaseResp payChangeValid(PayChangeReq req){
        BaseResp resp = new BaseResp();
        //判断币种类型
        if(StrUtil.isBlank(req.getCurrencyCode())){
            req.setCurrencyCode(RateTypeEnum.CNY.getType());
        }
        boolean flag = RateTypeEnum.exist(req.getCurrencyCode());
        if(!flag){
            String msg = "Unsupported currency code [" + req.getCurrencyCode() + "]";
            log.warn("[WechatHandler.ep] parameter verification error: {}", msg);
            return BaseResp.resp(RespCode.ILLEGAL_ARGUMENT.getCode(), msg, null);
        }
        //金额对应的小数位数(默认2位)
        if(req.getScale() == null){
            req.setScale(2);
        }
        switch (req.getChannelId()){
            case BizConstant.CHANNEL_ID_WX:
                return resp;
            case BizConstant.CHANNEL_ID_ALI:
                return resp;
            default:
                log.warn("Invalid channelId: {}", req.getChannelId());
                resp.setCode(RespCode.ERROR.getCode()).setMsg("Invalid channelId: " + req.getChannelId());
                return resp;
        }
    }

    /**
     * 微信支付类型参数校验
     * @param req
     * @return
     */
    private static BaseResp payWechatValid(PayReq req){
        BaseResp resp = new BaseResp();
        resp.setCode(RespCode.SUCCESS.getCode()).setMsg(RespCode.SUCCESS.getDesc());
        switch (req.getPayType()){
            case WechatPayConstant.PAY_TYPE_JSAPI:
                if(StrUtil.isBlank(req.getChannelUserId())){
                    log.warn("channelUserId is null");
                    resp.setCode(RespCode.ILLEGAL_ARGUMENT.getCode()).setMsg("channelUserId不能为空");
                }
                return resp;
            case WechatPayConstant.PAY_TYPE_H5:
                if(StrUtil.isBlank(req.getSceneInfo())){
                    log.warn("sceneInfo is null");
                    resp.setCode(RespCode.ILLEGAL_ARGUMENT.getCode()).setMsg("sceneInfo不能为空");
                }
                return resp;
            default:
                return resp;
        }
    }

    /**
     * 支付宝支付类型参数校验
     * @param req
     * @return
     */
    private static BaseResp payAliValid(PayReq req){
        BaseResp resp = new BaseResp();
        resp.setCode(RespCode.SUCCESS.getCode()).setMsg(RespCode.SUCCESS.getDesc());
        switch (req.getPayType()){
            case AliPayConstant.PAY_TYPE_PAGE:
            case AliPayConstant.PAY_TYPE_WAP:
                if(StrUtil.isBlank(req.getReturnUrl())){
                    log.warn("returnUrl is null");
                    resp.setCode(RespCode.ILLEGAL_ARGUMENT.getCode()).setMsg("returnUrl不能为空");
                }
                return resp;
            default:
                return resp;
        }
    }

}
